package com.corpgovernment.organization.service;

import com.corpgovernment.api.organization.bo.SyncOrgInfoReq;
import com.corpgovernment.api.organization.bo.SyncOrgInfoRsp;
import com.corpgovernment.api.organization.enums.UserOrgRelationStatusEnum;
import com.corpgovernment.api.organization.model.org.request.AddOrgRequest;
import com.corpgovernment.common.utils.EncryptUtils;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.corpgovernment.common.utils.LogSplicingUtils;
import com.corpgovernment.costcenter.entity.db.MbOrgCostInfo;
import com.corpgovernment.costcenter.service.impl.CostCenterServiceImpl;
import com.corpgovernment.organization.constant.CommonConst;
import com.corpgovernment.organization.constant.OrganizationConst;
import com.corpgovernment.organization.entity.db.*;
import com.corpgovernment.organization.enumm.DeliveryBaseDataTypeEnum;
import com.corpgovernment.organization.enumm.OrgTypeEnum;
import com.corpgovernment.organization.event.OrgInitEvent;
import com.corpgovernment.organization.model.org.dto.OrgInfoAllDto;
import com.corpgovernment.organization.service.impl.CommonInvoiceInfoService;
import com.corpgovernment.organization.service.impl.ExpressAddressServiceImpl;
import com.ctrip.corp.obt.generic.event.core.EventCenter;
import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SyncOrgInfoService {

    @Autowired
    private IOrganizationInfoService organizationInfoService;
    @Autowired
    private IOrgPayTypeService orgPayTypeService;
    @Autowired
    private CommonInvoiceInfoService commonInvoiceInfoService;
    @Autowired
    private ExpressAddressServiceImpl expressAddressService;
    @Autowired
    private IPostService postService;
    @Autowired
    private IUserOrgRelationService userOrgRelationService;
    @Autowired
    private CostCenterServiceImpl costCenterService;
    @Autowired
    private EventCenter eventCenter;
    @Autowired
    private IBdDeliveryBaseDataService bdDeliveryBaseDataService;

    public SyncOrgInfoRsp process(SyncOrgInfoReq request) {
        StringBuilder logContext = new StringBuilder();
        try {
            LogSplicingUtils.addLogContext(logContext, "开始导入组织信息");

            List<SyncOrgInfoReq.SyncOrganizationInfo> orgInfoList = request.getOrgInfoList();
            if (CollectionUtils.isEmpty(orgInfoList)) {
                return SyncOrgInfoRsp.success(Collections.emptyList());
            }
            List<SyncOrgInfoRsp.ErrorReason> errorReasonList = new ArrayList<>();
            List<SyncOrgInfoReq.SyncOrganizationInfo> addOrgList = new ArrayList<>();
            List<SyncOrgInfoReq.SyncOrganizationInfo> updateOrgList = new ArrayList<>();
            List<String> deleteOrgList = new ArrayList<>();

            long startTime = System.currentTimeMillis();
            List<OrgInfoAllDto> mbOrgAll = organizationInfoService.getOrgAllSomeParams();
            LogSplicingUtils.addLogContext(logContext, "查询数据库所有组织耗时：%s", System.currentTimeMillis() - startTime);

            Map<String, OrgInfoAllDto> orgAllMap = mbOrgAll.stream()
                .collect(Collectors.toMap(OrgInfoAllDto::getBusinessCode, Function.identity(), (k1, k2) -> k1));
            Map<String, List<OrgInfoAllDto>> parentMap =
                mbOrgAll.stream().filter(p -> StringUtils.isNotBlank(p.getParentBusinessCode()))
                    .collect(Collectors.groupingBy(OrgInfoAllDto::getParentBusinessCode));

            Map<String, OrgInfoAllDto> orgIdMap = mbOrgAll.stream()
                .collect(Collectors.toMap(OrgInfoAllDto::getOrgId, Function.identity(), (k1, k2) -> k1));

            List<BdDeliveryBaseData> baseDataList = bdDeliveryBaseDataService.queryAll();

            startTime = System.currentTimeMillis();
            Map<String, SyncOrgInfoReq.SyncOrganizationInfo> reqMap = new HashMap<>();
            List<SyncOrgInfoReq.SyncOrganizationInfo> organizationInfoList = new ArrayList<>();
            for (SyncOrgInfoReq.SyncOrganizationInfo organizationInfo : orgInfoList) {
                SyncOrgInfoRsp.ErrorReason errorReason = this.checkParams(organizationInfo, baseDataList);
                if (Objects.nonNull(errorReason)) {
                    errorReasonList.add(errorReason);
                    continue;
                }
                SyncOrgInfoRsp.ErrorReason costCenterReason = checkCostCenterInfo(organizationInfo, orgAllMap);
                if (Objects.nonNull(costCenterReason)) {
                    errorReasonList.add(costCenterReason);
                    continue;
                }
                reqMap.put(organizationInfo.getBasicInfo().getOrgId(), organizationInfo);
                organizationInfoList.add(organizationInfo);
            }
            LogSplicingUtils.addLogContext(logContext, "基础校验耗时：%s", System.currentTimeMillis() - startTime);

            startTime = System.currentTimeMillis();
            getChildren(organizationInfoList, reqMap, orgAllMap, errorReasonList);
            LogSplicingUtils.addLogContext(logContext, "遍历父级节点耗时：%s", System.currentTimeMillis() - startTime);

            startTime = System.currentTimeMillis();
            reqMap.forEach((key, orgInfo) -> {
                SyncOrgInfoReq.BasicInfo basicInfo = orgInfo.getBasicInfo();
                basicInfo.setIsActive(Objects.nonNull(basicInfo.getIsActive()) ? basicInfo.getIsActive() : true);
                basicInfo.setIsDelete(Objects.nonNull(basicInfo.getIsDelete()) ? basicInfo.getIsDelete() : false);

                if (BooleanUtils.isTrue(basicInfo.getIsDelete())) {
                    // 删除
                    List<String> allOrgIds = new ArrayList<>();
                    SyncOrgInfoRsp.ErrorReason errorReason = deleteCheckParams(basicInfo, parentMap, allOrgIds);
                    if (Objects.nonNull(errorReason)) {
                        errorReasonList.add(errorReason);
                        return;
                    }
                    deleteOrgList.addAll(allOrgIds);
                }
            });

            if (CollectionUtils.isNotEmpty(deleteOrgList)) {
                deleteOrgList.forEach(reqMap::remove);
            }

            reqMap.forEach((key, orgInfo) -> {
                SyncOrgInfoReq.BasicInfo basicInfo = orgInfo.getBasicInfo();
                basicInfo.setLevel(1);
                OrgInfoAllDto orgInfoAllDto = orgAllMap.get(key);
                if (Objects.nonNull(orgInfoAllDto)) {
                    updateOrgList.add(orgInfo);
                } else {
                    addOrgList.add(orgInfo);
                }
            });
            LogSplicingUtils.addLogContext(logContext, "增/删/改分组耗时：%s", System.currentTimeMillis() - startTime);

            LogSplicingUtils.addLogContext(logContext, "处理条数,增-删-改:[%s-%s-%s]", addOrgList.size(), deleteOrgList.size(),
                updateOrgList.size());
            // 新增组织
            add(addOrgList, orgAllMap);
            // 修改组织
            update(updateOrgList, orgAllMap);
            // 删除组织
            delete(deleteOrgList);
            // 修改组织层级
            updateLevel();
            return SyncOrgInfoRsp.success(errorReasonList);
        } catch (Exception e) {
            log.error("导入组织异常", e);
            return SyncOrgInfoRsp.error();
        } finally {
            log.info("{}", logContext);
        }
    }

    private void updateLevel() {
        List<OrgInfoAllDto> mbOrgAll = organizationInfoService.getOrgAllSomeParams();
        List<OrgInfoAllDto> topOrgList =
            mbOrgAll.stream().filter(item -> StringUtils.isBlank(item.getParentId())).collect(Collectors.toList());
        Map<String, List<OrgInfoAllDto>> parentMap =
            mbOrgAll.stream().filter(item -> StringUtils.isNotBlank(item.getParentId()))
                .collect(Collectors.groupingBy(item -> item.getParentId()));

        List<MbOrgInfo> mbOrgInfoList = new ArrayList<>();
        for (OrgInfoAllDto topOrg : topOrgList) {
            Integer level = 1;
            if (level.compareTo(topOrg.getLevel()) != 0) {
                MbOrgInfo mbOrgInfo = new MbOrgInfo();
                mbOrgInfo.setOrgId(topOrg.getOrgId());
                mbOrgInfo.setLevel(level);
                mbOrgInfoList.add(mbOrgInfo);
            }
            List<OrgInfoAllDto> orgInfoAllDtos = parentMap.get(topOrg.getOrgId());
            getLevel(mbOrgInfoList, parentMap, orgInfoAllDtos, level);
        }

        if (CollectionUtils.isNotEmpty(mbOrgInfoList)) {
            mbOrgInfoList.forEach(organizationInfoService::update);
        }
    }

    private void getLevel(List<MbOrgInfo> mbOrgInfoList, Map<String, List<OrgInfoAllDto>> parentMap,
        List<OrgInfoAllDto> orgInfoAllDtos, Integer level) {
        if (CollectionUtils.isEmpty(orgInfoAllDtos)) {
            return;
        }
        level = level + 1;
        for (OrgInfoAllDto orgInfo : orgInfoAllDtos) {
            Integer levelNew = new Integer(level);
            if (levelNew.compareTo(orgInfo.getLevel()) != 0) {
                MbOrgInfo mbOrgInfo = new MbOrgInfo();
                mbOrgInfo.setOrgId(orgInfo.getOrgId());
                mbOrgInfo.setLevel(levelNew);
                mbOrgInfoList.add(mbOrgInfo);
            }
            List<OrgInfoAllDto> orgInfoAllDtoList = parentMap.get(orgInfo.getOrgId());
            getLevel(mbOrgInfoList, parentMap, orgInfoAllDtoList, level);
        }
    }

    private void getChildren(List<SyncOrgInfoReq.SyncOrganizationInfo> organizationInfoList,
        Map<String, SyncOrgInfoReq.SyncOrganizationInfo> reqMap,
        Map<String, OrgInfoAllDto> orgAllMap,
        List<SyncOrgInfoRsp.ErrorReason> errorReasonList) {
        HashMap<String, String> allExecuteMap = new HashMap<>();
        for (SyncOrgInfoReq.SyncOrganizationInfo syncOrganizationInfo : organizationInfoList) {

            // 递归时候就会把父级也给校验完成 不需要重复校验
            if (Objects.nonNull(allExecuteMap.get(syncOrganizationInfo.getBasicInfo().getOrgId()))) {
                continue;
            }

            // 顶级组织
            if (StringUtils.isBlank(syncOrganizationInfo.getBasicInfo().getParentOrgId())) {
                continue;
            }

            SyncOrgInfoReq.SyncOrganizationInfo organizationInfo =
                reqMap.get(syncOrganizationInfo.getBasicInfo().getOrgId());
            if (Objects.nonNull(organizationInfo)) {
                // value: request：接口进入数据 database：数据库数据
                Map<String, String> executeMap = new HashMap<>();
                SyncOrgInfoReq.BasicInfo basicInfo = organizationInfo.getBasicInfo();
                // 存入已经执行过的组织中
                executeMap.put(organizationInfo.getBasicInfo().getOrgId(), SOURCE_REQUEST);
                // 递归结果
                String result = getParentOrg(basicInfo.getOrgId(), reqMap, orgAllMap, executeMap);
                allExecuteMap.putAll(executeMap);
                if (StringUtils.isBlank(result)) {
                    continue;
                }

                for (String key : executeMap.keySet()) {
                    String source = executeMap.get(key);
                    reqMap.remove(key);
                    if (SOURCE_REQUEST.equals(source)) {
                        SyncOrgInfoRsp.ErrorReason errorReason = new SyncOrgInfoRsp.ErrorReason();
                        errorReason.setOrgId(key);
                        errorReason.setMessage(result);
                        errorReasonList.add(errorReason);
                    }
                }
            }
        }
    }

    private final static String SOURCE_DATABASE = "database";
    private final static String SOURCE_REQUEST = "request";
    private final static String ERROR_MSG_SUC = "";
    private final static String ERROR_MSG_NULL_TOP_ORG = "找不到父级节点";
    private final static String ERROR_MSG_REPLACE_EXECUTE = "数据异常,父级组织与子级组织互相关联";

    private String getParentOrg(String orgId,
        Map<String, SyncOrgInfoReq.SyncOrganizationInfo> reqMap,
        Map<String, OrgInfoAllDto> orgAllMap,
        Map<String, String> executeMap) {

        SyncOrgInfoReq.SyncOrganizationInfo syncOrganizationInfo = reqMap.get(orgId);
        if (Objects.nonNull(syncOrganizationInfo)) {
            // 存入已经执行过的组织中
            executeMap.put(orgId, SOURCE_REQUEST);

            SyncOrgInfoReq.BasicInfo basicInfo = syncOrganizationInfo.getBasicInfo();
            // 说明是顶级组织
            if (StringUtils.isBlank(basicInfo.getParentOrgId())) {
                return ERROR_MSG_SUC;
            }
            // 已经递归过
            if (executeMap.get(basicInfo.getParentOrgId()) != null) {
                return ERROR_MSG_REPLACE_EXECUTE;
            }

            // 继续递归
            return getParentOrg(basicInfo.getParentOrgId(), reqMap, orgAllMap, executeMap);
        } else {
            // 存入已经执行过的组织中
            executeMap.put(orgId, SOURCE_DATABASE);

            OrgInfoAllDto orgInfoAllDto = orgAllMap.get(orgId);
            // 找不到父级组织
            if (Objects.isNull(orgInfoAllDto)) {
                return ERROR_MSG_NULL_TOP_ORG;
            }
            // 说明是顶级组织
            if (StringUtils.isBlank(orgInfoAllDto.getParentBusinessCode())) {
                return ERROR_MSG_SUC;
            }
            // 进来的第一次说明已经和数据库关联上了
            // 继续递归避免死循环
            return getParentOrg(orgInfoAllDto.getParentBusinessCode(), reqMap, orgAllMap, executeMap);
        }

    }

    private void delete(List<String> deleteOrgList) {
        if (CollectionUtils.isEmpty(deleteOrgList)) {
            return;
        }
        for (String orgId : deleteOrgList) {
            // 删除关联发票信息
            commonInvoiceInfoService.deleteByOrgId(orgId);
            // 删除关联配送信息
            expressAddressService.deleteByOrgId(orgId);
            // 删除关联支付信息
            orgPayTypeService.delete(Collections.singletonList(orgId), null, null, null, true);
            // 删除职级信息
            postService.deleteByOrgIds(Collections.singletonList(orgId));
            // 删除成本中心
            costCenterService.deleteByOrgId(orgId);
            // 删除部门 (需查询是否关联角色, 清除角色--部门中间表数据)
            MbOrgInfo mbOrgInfo = organizationInfoService.selectOneByOrgId(orgId);
            if (Objects.nonNull(mbOrgInfo)) {
                organizationInfoService.delRoleOrgDataInfo(null, mbOrgInfo);
            }
        }
        // 删除组织
        organizationInfoService.deleteByOrgIds(deleteOrgList);
    }

    private void update(List<SyncOrgInfoReq.SyncOrganizationInfo> updateOrgList, Map<String, OrgInfoAllDto> orgAllMap) {
        if (CollectionUtils.isEmpty(updateOrgList)) {
            return;
        }

        List<MbOrgInfo> mbOrgInfoList = new ArrayList<>();
        List<MbPostInfo> mbPostInfoList = new ArrayList<>();
        List<MbCommonInvoiceInfo> mbCommonInvoiceInfoList = new ArrayList<>();
        List<MbExpressAddress> mbExpressAddressList = new ArrayList<>();
        List<AddOrgRequest> orgCostCenterList = new ArrayList<>();
        for (SyncOrgInfoReq.SyncOrganizationInfo orgInfo : updateOrgList) {
            MbOrgInfo mbOrgInfo = new MbOrgInfo();
            SyncOrgInfoReq.BasicInfo basicInfo = orgInfo.getBasicInfo();
            mbOrgInfo.setName(EncryptUtils.sm4Encrypt(basicInfo.getName()));
            mbOrgInfo.setOrgType(basicInfo.getType());
            OrgInfoAllDto orgInfoAllDto = orgAllMap.get(basicInfo.getOrgId());
            mbOrgInfo.setOrgId(orgInfoAllDto.getOrgId());
            OrgInfoAllDto parentOrgInfoAllDto = orgAllMap.get(basicInfo.getParentOrgId());
            if (Objects.nonNull(parentOrgInfoAllDto)) {
                mbOrgInfo.setParentId(parentOrgInfoAllDto.getOrgId());
            }
            if (StringUtils.isBlank(basicInfo.getParentOrgId())) {
                mbOrgInfo.setParentId("");
            }
            mbOrgInfo.setLevel(basicInfo.getLevel());
            mbOrgInfo.setBusinessCode(basicInfo.getOrgId());
            mbOrgInfo.setParentBusinessCode(basicInfo.getParentOrgId());
            if (orgInfo.getContactInfo() != null) {
                mbOrgInfo.setContactAreaCode(orgInfo.getContactInfo().getContactCountryCode());
                mbOrgInfo.setContactEmail(orgInfo.getContactInfo().getContactEmail());
                mbOrgInfo.setContactName(EncryptUtils.sm4Encrypt(orgInfo.getContactInfo().getContactName()));
                mbOrgInfo.setContactPhone(EncryptUtils.sm4Encrypt(orgInfo.getContactInfo().getContactPhone()));
            }
            mbOrgInfo.setValid(basicInfo.getIsActive() ? CommonConst.TRUE : CommonConst.FALSE);
            mbOrgInfo.setDatachangeLasttime(new Date());
            // 组织
            mbOrgInfoList.add(mbOrgInfo);
            // 职级
            if (CollectionUtils.isNotEmpty(orgInfo.getPostInfoList())) {
                for (SyncOrgInfoReq.PostInfo postInfo : orgInfo.getPostInfoList()) {
                    MbPostInfo mbPostInfo = new MbPostInfo();
                    mbPostInfo.setOrgId(basicInfo.getOrgId());
                    mbPostInfo.setName(postInfo.getName());
                    mbPostInfo.setIsDeleted(false);
                    mbPostInfoList.add(mbPostInfo);
                }
            }
            // 发票
            if (CollectionUtils.isNotEmpty(orgInfo.getInvoiceInfoList())) {
                mbCommonInvoiceInfoList.addAll(getInvoiceInfo(orgInfo));
            }
            // 邮寄地址
            if (CollectionUtils.isNotEmpty(orgInfo.getDeliveryAddressList())) {
                mbExpressAddressList.addAll(getDeliveryAddress(orgInfo));
            }

            // 编辑时成本中心和默认成本中心可以改为空
            AddOrgRequest orgCostCenter = new AddOrgRequest();
            orgCostCenter.setOrgId(mbOrgInfo.getOrgId());
            orgCostCenter.setType(mbOrgInfo.getOrgType());
            AddOrgRequest.CostCenterInfo addCostCenterDefault = new AddOrgRequest.CostCenterInfo();
            // 成本中心
            if (CollectionUtils.isEmpty(orgInfo.getCostCenterInfoList())){
                orgCostCenter.setCostCenterInfoList(null);
            } else {
                orgCostCenter.setCostCenterInfoList(orgInfo.getCostCenterInfoList().stream().map(item -> {
                    AddOrgRequest.CostCenterInfo addCostCenterInfo = new AddOrgRequest.CostCenterInfo();
                    addCostCenterInfo.setCostCenterCode(item.getCostCenterCode());
                    addCostCenterInfo.setCostCenterName(item.getCostCenterName());
                    return addCostCenterInfo;
                }).collect(Collectors.toList()));

                if(orgInfo.getCostCenterInfoDefault() != null) {
                    addCostCenterDefault.setCostCenterName(orgInfo.getCostCenterInfoDefault().getCostCenterName());
                    addCostCenterDefault.setCostCenterCode(orgInfo.getCostCenterInfoDefault().getCostCenterCode());
                }
            }
            orgCostCenter.setCostCenterInfoDefault(addCostCenterDefault);
            orgCostCenterList.add(orgCostCenter);
        }
        // 修改组织
        if (CollectionUtils.isNotEmpty(mbOrgInfoList)) {
            organizationInfoService.batchUpdate(mbOrgInfoList);
        }
        // 修改职级
        if (CollectionUtils.isNotEmpty(mbPostInfoList)) {
            for (MbPostInfo mbPostInfo : mbPostInfoList) {
                postService.createPost(mbPostInfo.getName(), mbPostInfo.getOrgId());
            }
        }
        // 插入发票信息
        if (CollectionUtils.isNotEmpty(mbCommonInvoiceInfoList)) {
            mbCommonInvoiceInfoList.stream().collect(Collectors.groupingBy(MbCommonInvoiceInfo::getOrgId))
                .forEach((key, invoiceList) -> {
                    commonInvoiceInfoService.deleteByOrgId(key);
                });
            commonInvoiceInfoService.batchInsertCommonInvoiceInfo(mbCommonInvoiceInfoList);
        }
        // 插入配送地址
        if (CollectionUtils.isNotEmpty(mbExpressAddressList)) {
            mbExpressAddressList.stream().collect(Collectors.groupingBy(MbExpressAddress::getOrgId))
                .forEach((key, addressList) -> {
                    expressAddressService.deleteByOrgId(key);
                });
            expressAddressService.insertBatch(mbExpressAddressList);
        }
        // 编辑成本中心和默认成本中心
        packageSaveCostCenter(orgCostCenterList);
    }

    private void add(List<SyncOrgInfoReq.SyncOrganizationInfo> addOrgList, Map<String, OrgInfoAllDto> orgAllMap) {
        if (CollectionUtils.isEmpty(addOrgList)) {
            return;
        }
        List<MbOrgInfo> mbOrgInfoList = new ArrayList<>();
        List<MbPostInfo> mbPostInfoList = new ArrayList<>();
        List<MbCommonInvoiceInfo> mbCommonInvoiceInfoList = new ArrayList<>();
        List<MbExpressAddress> mbExpressAddressList = new ArrayList<>();
        List<AddOrgRequest> orgCostCenterList = new ArrayList<>();
        for (SyncOrgInfoReq.SyncOrganizationInfo orgInfo : addOrgList) {
            MbOrgInfo mbOrgInfo = new MbOrgInfo();
            SyncOrgInfoReq.BasicInfo basicInfo = orgInfo.getBasicInfo();
            mbOrgInfo.setName(EncryptUtils.sm4Encrypt(basicInfo.getName()));
            mbOrgInfo.setOrgType(basicInfo.getType());
            // 新增用父级查询 因为父级可能是数据库存在的
            OrgInfoAllDto orgInfoAllDto = orgAllMap.get(basicInfo.getParentOrgId());
            if (Objects.nonNull(orgInfoAllDto)) {
                mbOrgInfo.setParentId(orgInfoAllDto.getOrgId());
                mbOrgInfo.setOrgId(basicInfo.getOrgId());
            } else {
                mbOrgInfo.setParentId(basicInfo.getParentOrgId());
                mbOrgInfo.setOrgId(basicInfo.getOrgId());
            }
            if (StringUtils.isBlank(basicInfo.getParentOrgId())) {
                mbOrgInfo.setParentId("");
            }
            mbOrgInfo.setLevel(basicInfo.getLevel());
            mbOrgInfo.setBusinessCode(basicInfo.getOrgId());
            mbOrgInfo.setParentBusinessCode(basicInfo.getParentOrgId());
            if (orgInfo.getContactInfo() != null) {
                mbOrgInfo.setContactAreaCode(orgInfo.getContactInfo().getContactCountryCode());
                mbOrgInfo.setContactEmail(orgInfo.getContactInfo().getContactEmail());
                mbOrgInfo.setContactName(EncryptUtils.sm4Encrypt(orgInfo.getContactInfo().getContactName()));
                mbOrgInfo.setContactPhone(EncryptUtils.sm4Encrypt(orgInfo.getContactInfo().getContactPhone()));
            }
            mbOrgInfo.setValid(basicInfo.getIsActive() ? CommonConst.TRUE : CommonConst.FALSE);
            mbOrgInfo.setDatachangeCreatetime(new Date());
            mbOrgInfo.setDatachangeLasttime(new Date());
            mbOrgInfo.setIsBackground(false);
            mbOrgInfo.setDeleteTime(new Date(0));
            // 组织
            mbOrgInfoList.add(mbOrgInfo);
            // 职级
            if (CollectionUtils.isNotEmpty(orgInfo.getPostInfoList())) {
                mbPostInfoList.addAll(getPostInfo(orgInfo));
            }
            // 发票
            if (CollectionUtils.isNotEmpty(orgInfo.getInvoiceInfoList())) {
                mbCommonInvoiceInfoList.addAll(getInvoiceInfo(orgInfo));
            }
            // 邮寄地址
            if (CollectionUtils.isNotEmpty(orgInfo.getDeliveryAddressList())) {
                mbExpressAddressList.addAll(getDeliveryAddress(orgInfo));
            }

            // 初始化组织设置
            OrgInitEvent orgInitEvent = new OrgInitEvent();
            OrgInitEvent.InitOrgPayType initOrgPayType = new OrgInitEvent.InitOrgPayType();
            initOrgPayType.setOrgId(basicInfo.getOrgId());
            initOrgPayType.setOrgType(basicInfo.getType());
            orgInitEvent.setInitOrgPayType(initOrgPayType);
            eventCenter.post(orgInitEvent);

            // 成本中心
            if (CollectionUtils.isNotEmpty(orgInfo.getCostCenterInfoList())){
                AddOrgRequest orgCostCenter = new AddOrgRequest();
                orgCostCenter.setOrgId(mbOrgInfo.getOrgId());
                orgCostCenter.setType(mbOrgInfo.getOrgType());
                orgCostCenter.setCostCenterInfoList(orgInfo.getCostCenterInfoList().stream().map(item -> {
                    AddOrgRequest.CostCenterInfo addCostCenterInfo = new AddOrgRequest.CostCenterInfo();
                    addCostCenterInfo.setCostCenterCode(item.getCostCenterCode());
                    addCostCenterInfo.setCostCenterName(item.getCostCenterName());
                    return addCostCenterInfo;
                }).collect(Collectors.toList()));

                AddOrgRequest.CostCenterInfo addCostCenterDefault = new AddOrgRequest.CostCenterInfo();
                if(orgInfo.getCostCenterInfoDefault() != null) {
                    addCostCenterDefault.setCostCenterName(orgInfo.getCostCenterInfoDefault().getCostCenterName());
                    addCostCenterDefault.setCostCenterCode(orgInfo.getCostCenterInfoDefault().getCostCenterCode());
                }
                orgCostCenter.setCostCenterInfoDefault(addCostCenterDefault);
                orgCostCenterList.add(orgCostCenter);
            }
        }
        // 插入组织
        organizationInfoService.batchInsertOrgInfo(mbOrgInfoList);
        // 插入职级
        postService.batchInsertPostInfo(mbPostInfoList);
        // 插入发票信息
        commonInvoiceInfoService.batchInsertCommonInvoiceInfo(mbCommonInvoiceInfoList);
        // 插入配送地址
        expressAddressService.insertBatch(mbExpressAddressList);

        // 新增成本中心 和 默认成本中心
        if (CollectionUtils.isNotEmpty(orgCostCenterList)) {
            packageSaveCostCenter(orgCostCenterList);
        }
    }

    private void packageSaveCostCenter(List<AddOrgRequest> orgCostCenterList) {
        log.info("机构导入机构，成本中心默认成本中心类型{}", JsonUtils.toJsonString(orgCostCenterList));
        if (CollectionUtils.isEmpty(orgCostCenterList)) {
            return;
        }
        orgCostCenterList.forEach(costCenterInfo -> {
            if(CollectionUtils.isEmpty(costCenterInfo.getCostCenterInfoList())) {
                return;
            }
            // 成本中心
            costCenterService.saveCostCenterInfoByOrg(costCenterInfo.getOrgId(), costCenterInfo.getCostCenterInfoList());
            // 默认成本中心
            if(null != costCenterInfo.getCostCenterInfoDefault()
                    && null != costCenterInfo.getCostCenterInfoDefault().getCostCenterCode()) {
                costCenterService.saveOrgCostDefaultDepartmentByOrg(costCenterInfo.getOrgId(), costCenterInfo.getCostCenterInfoDefault());
            }
        });
    }

    private SyncOrgInfoRsp.ErrorReason deleteCheckParams(SyncOrgInfoReq.BasicInfo basicInfo,
        Map<String, List<OrgInfoAllDto>> parentMap,
        List<String> allOrgIds) {
        SyncOrgInfoRsp.ErrorReason errorReason = new SyncOrgInfoRsp.ErrorReason();
        errorReason.setOrgId(basicInfo.getOrgId());
        recursionParentAll(basicInfo.getOrgId(), parentMap, allOrgIds);
        allOrgIds.add(basicInfo.getOrgId());
        int count = userOrgRelationService.countEmployee(UserOrgRelationStatusEnum.LEAVE.getStatus(), allOrgIds);
        if (count > 0) {
            errorReason.setMessage("该组织下有未删除的员工");
            return errorReason;
        }
        return null;
    }

    public static OrgInfoAllDto findRecentCompanyId(String businessCode, Map<String, OrgInfoAllDto> orgAllMap) {
        // 查询
        OrgInfoAllDto orgInfoAllDto = orgAllMap.get(businessCode);
        if (orgInfoAllDto == null) {
            return null;
        }
        if (orgInfoAllDto.getOrgType().equals(OrganizationConst.DEPARTMENT)) {
            return findRecentCompanyId(orgInfoAllDto.getParentBusinessCode(), orgAllMap);
        } else {
            return orgInfoAllDto;
        }
    }

    private SyncOrgInfoRsp.ErrorReason checkCostCenterInfo(SyncOrgInfoReq.SyncOrganizationInfo syncOrganizationInfo, Map<String, OrgInfoAllDto> orgAllMap) {
        SyncOrgInfoRsp.ErrorReason errorReason = new SyncOrgInfoRsp.ErrorReason();
        SyncOrgInfoReq.BasicInfo basicInfo = syncOrganizationInfo.getBasicInfo();
        errorReason.setOrgId(basicInfo.getOrgId());
        List<SyncOrgInfoReq.CostCenterInfo> costCenterInfoList = syncOrganizationInfo.getCostCenterInfoList();
        SyncOrgInfoReq.CostCenterInfo costCenterInfoDefault = syncOrganizationInfo.getCostCenterInfoDefault();
        if (CollectionUtils.isEmpty(costCenterInfoList) && costCenterInfoDefault == null) {
            return null;
        }
        log.info("机构同步：成本中心{}，默认成本中心{}", JsonUtils.toJsonString(costCenterInfoList), JsonUtils.toJsonString(costCenterInfoDefault));
        if(costCenterInfoDefault != null) {
            if(CollectionUtils.isEmpty(costCenterInfoList) || !costCenterInfoList.contains(costCenterInfoDefault)) {
                errorReason.setMessage("默认成本中心不为所属成本中心");
                return errorReason;
            }
            if (StringUtils.isBlank(costCenterInfoDefault.getCostCenterCode())) {
                errorReason.setMessage("默认成本中心编码不能为空");
                return errorReason;
            }
            if (StringUtils.isBlank(costCenterInfoDefault.getCostCenterName())) {
                errorReason.setMessage("默认成本中心名称不能为空");
                return errorReason;
            }
        }

        Map<String, String> costCenterMap = new HashMap<>(costCenterInfoList.size());
        for (SyncOrgInfoReq.CostCenterInfo costCenterInfo : costCenterInfoList) {
            if (StringUtils.isBlank(costCenterInfo.getCostCenterCode())) {
                errorReason.setMessage("成本中心编码不能为空");
                return errorReason;
            }
            if (StringUtils.isBlank(costCenterInfo.getCostCenterName())) {
                errorReason.setMessage("成本中心名称不能为空");
                return errorReason;
            }

            if(costCenterMap.containsKey(costCenterInfo.getCostCenterCode())) {
                errorReason.setMessage("本次导入新增的所属成本中心编码有重复");
                return errorReason;
            } else {
                costCenterMap.put(costCenterInfo.getCostCenterCode(), costCenterInfo.getCostCenterName());
            }
        }

        // 部门需要校验成本中心
        if (OrgTypeEnum.D.getCode().equals(basicInfo.getType())) {
            OrgInfoAllDto companyOrgInfo = findRecentCompanyId(basicInfo.getParentOrgId(), orgAllMap);
            if (null == companyOrgInfo) {
                errorReason.setMessage("请先导入部门的直属公司");
                return errorReason;
            }
            Map<String, MbOrgCostInfo> costCenterCodeMap =
                    costCenterService.costCenterCodeMapByCompany(companyOrgInfo.getOrgId());

            for (SyncOrgInfoReq.CostCenterInfo costCenterInfo : costCenterInfoList) {
                MbOrgCostInfo mbOrgCostInfo = costCenterCodeMap.get(costCenterInfo.getCostCenterCode());
                if (null == mbOrgCostInfo){
                    errorReason.setMessage("成本中心编码在系统中不存在");
                    return errorReason;
                }
                if (!mbOrgCostInfo.getCostCenterName().equals(costCenterInfo.getCostCenterName())) {
                    errorReason.setMessage("成本中心名称不正确");
                    return errorReason;
                }
            }
        } else {
            Map<String, MbOrgCostInfo> costCenterCodeMap =
                    costCenterService.costCenterCodeMapByCompany(basicInfo.getOrgId());
            if(costCenterCodeMap != null) {
                for (SyncOrgInfoReq.CostCenterInfo costCenterInfo : costCenterInfoList) {
                    MbOrgCostInfo mbOrgCostInfo = costCenterCodeMap.get(costCenterInfo.getCostCenterCode());
                    if (mbOrgCostInfo != null && !mbOrgCostInfo.getCostCenterName().equals(costCenterInfo.getCostCenterName())) {
                        errorReason.setMessage("成本中心名称不正确");
                        return errorReason;
                    }
                }
            }
        }
        return null;
    }

    private SyncOrgInfoRsp.ErrorReason checkParams(SyncOrgInfoReq.SyncOrganizationInfo syncOrganizationInfo,
        List<BdDeliveryBaseData> baseDataList) {
        SyncOrgInfoRsp.ErrorReason errorReason = new SyncOrgInfoRsp.ErrorReason();

        SyncOrgInfoReq.BasicInfo basicInfo = syncOrganizationInfo.getBasicInfo();
        errorReason.setOrgId(basicInfo.getOrgId());
        if (StringUtils.isBlank(basicInfo.getOrgId())) {
            errorReason.setMessage("组织编码不能为空");
            return errorReason;
        }
        if (StringUtils.isBlank(basicInfo.getName())) {
            errorReason.setMessage("组织名称不能为空");
            return errorReason;
        }
        if (StringUtils.isBlank(basicInfo.getType())) {
            errorReason.setMessage("组织类型不能为空");
            return errorReason;
        }

        if (basicInfo.getOrgId().equalsIgnoreCase(basicInfo.getParentOrgId())) {
            errorReason.setMessage("组织编码与父级组织编码不能相等");
            return errorReason;
        }

        if (StringUtils.isBlank(basicInfo.getParentOrgId()) && OrgTypeEnum.D.getCode().equals(basicInfo.getType())) {
            errorReason.setMessage("顶级组织的类型不能为部门");
            return errorReason;
        }

        SyncOrgInfoReq.ContactInfo contactInfo = syncOrganizationInfo.getContactInfo();
        if (Objects.nonNull(contactInfo)) {
            if (StringUtils.isBlank(contactInfo.getContactName())) {
                errorReason.setMessage("联系人名字不能为空");
                return errorReason;
            }
            if (StringUtils.isBlank(contactInfo.getContactPhone())) {
                errorReason.setMessage("联系人电话不能为空");
                return errorReason;
            }
        }

        List<SyncOrgInfoReq.InvoiceInfo> invoiceInfoList = syncOrganizationInfo.getInvoiceInfoList();
        if (CollectionUtils.isNotEmpty(invoiceInfoList)) {
            for (SyncOrgInfoReq.InvoiceInfo invoiceInfo : invoiceInfoList) {
                if (StringUtils.isBlank(invoiceInfo.getInvoiceTitle())) {
                    errorReason.setMessage("发票抬头不能为空");
                    return errorReason;
                }
                if (StringUtils.isBlank(invoiceInfo.getTaxId())) {
                    errorReason.setMessage("纳税人识别号不能为空");
                    return errorReason;
                }
                if (StringUtils.isBlank(invoiceInfo.getAccountBank())) {
                    errorReason.setMessage("开户行不能为空");
                    return errorReason;
                }
                if (StringUtils.isBlank(invoiceInfo.getAccountCardNo())) {
                    errorReason.setMessage("银行账号不能为空");
                    return errorReason;
                }
                if (StringUtils.isBlank(invoiceInfo.getCorporationPhone())) {
                    errorReason.setMessage("单位电话不能为空");
                    return errorReason;
                }
                if (StringUtils.isBlank(invoiceInfo.getCorporationAddress())) {
                    errorReason.setMessage("单位地址不能为空");
                    return errorReason;
                }
            }
        }

        List<BdDeliveryBaseData> provideList = baseDataList.stream()
            .filter(item -> DeliveryBaseDataTypeEnum.P.name().equals(item.getType())).collect(Collectors.toList());
        List<BdDeliveryBaseData> cityList = baseDataList.stream()
            .filter(item -> DeliveryBaseDataTypeEnum.C.name().equals(item.getType())).collect(Collectors.toList());
        List<BdDeliveryBaseData> districtList = baseDataList.stream()
            .filter(item -> DeliveryBaseDataTypeEnum.A.name().equals(item.getType())).collect(Collectors.toList());

        List<SyncOrgInfoReq.DeliveryAddress> deliveryAddressList = syncOrganizationInfo.getDeliveryAddressList();
        if (CollectionUtils.isNotEmpty(deliveryAddressList)) {
            for (SyncOrgInfoReq.DeliveryAddress deliveryAddress : deliveryAddressList) {
                if (StringUtils.isBlank(deliveryAddress.getProvinceName())) {
                    errorReason.setMessage("省名不能为空");
                    return errorReason;
                }
                if (StringUtils.isBlank(deliveryAddress.getCityName())) {
                    errorReason.setMessage("市名不能为空");
                    return errorReason;
                }
                if (StringUtils.isBlank(deliveryAddress.getDistrictName())) {
                    errorReason.setMessage("区名不能为空");
                    return errorReason;
                }
                if (StringUtils.isBlank(deliveryAddress.getAddress())) {
                    errorReason.setMessage("详细地址不能为空");
                    return errorReason;
                }
                if (StringUtils.isBlank(deliveryAddress.getRecipientName())) {
                    errorReason.setMessage("收件人姓名不能为空");
                    return errorReason;
                }
                if (StringUtils.isBlank(deliveryAddress.getRecipientPhone())) {
                    errorReason.setMessage("收件人电话不能为空");
                    return errorReason;
                }

                Optional<BdDeliveryBaseData> provideFirst = provideList.stream()
                    .filter(item -> item.getName().indexOf(deliveryAddress.getProvinceName()) >= 0).findFirst();
                if (provideFirst.isPresent()) {
                    deliveryAddress.setProvince(provideFirst.get().getCode());
                    deliveryAddress.setProvinceName(provideFirst.get().getName());
                } else {
                    errorReason
                        .setMessage("省份名称匹配失败,请填写正确的名称,例如湖南省支持（湖南,湖南省）,当前入参为：" + deliveryAddress.getProvinceName());
                    return errorReason;
                }

                Optional<BdDeliveryBaseData> cityFirst = cityList.stream()
                    .filter(item -> item.getName().indexOf(deliveryAddress.getCityName()) >= 0).findFirst();
                if (cityFirst.isPresent()) {
                    deliveryAddress.setCity(cityFirst.get().getCode());
                    deliveryAddress.setCityName(cityFirst.get().getName());
                } else {
                    errorReason.setMessage("地级市匹配失败,请填写正确的名称,例如长沙市支持（长沙,长沙市）,当前入参为：" + deliveryAddress.getCityName());
                    return errorReason;
                }

                Optional<BdDeliveryBaseData> districtFirst = districtList.stream()
                    .filter(item -> item.getName().indexOf(deliveryAddress.getDistrictName()) == 0).findFirst();
                if (districtFirst.isPresent()) {
                    deliveryAddress.setDistrict(districtFirst.get().getCode());
                    deliveryAddress.setDistrictName(districtFirst.get().getName());
                } else {
                    errorReason
                        .setMessage("行政区,县市级匹配失败,请填写正确的名称,例如曹县支持（曹县）,当前入参为：" + deliveryAddress.getDistrictName());
                    return errorReason;
                }
            }

            List<SyncOrgInfoReq.CostCenterInfo> costCenterInfoList = syncOrganizationInfo.getCostCenterInfoList();
            if (CollectionUtils.isNotEmpty(costCenterInfoList)){
                for (SyncOrgInfoReq.CostCenterInfo costCenterInfo:costCenterInfoList){
                    if (StringUtils.isBlank(costCenterInfo.getCostCenterCode())){
                        errorReason.setMessage("成本中心编码不能为空");
                        return errorReason;
                    }
                    if (StringUtils.isBlank(costCenterInfo.getCostCenterName())){
                        errorReason.setMessage("成本中心名称不能为空");
                        return errorReason;
                    }
                }
            }
        }
        return null;
    }

    private void recursionParentAll(String businessCode, Map<String, List<OrgInfoAllDto>> parentMap,
        List<String> returnList) {
        List<OrgInfoAllDto> mbOrgInfoList = parentMap.get(businessCode);
        if (CollectionUtils.isNotEmpty(mbOrgInfoList)) {
            for (OrgInfoAllDto mbOrgInfo : mbOrgInfoList) {
                returnList.add(mbOrgInfo.getBusinessCode());
                recursionParentAll(mbOrgInfo.getBusinessCode(), parentMap, returnList);
            }
        }
    }

    private List<MbPostInfo> getPostInfo(SyncOrgInfoReq.SyncOrganizationInfo syncOrgInfoDto) {
        List<MbPostInfo> mbPostInfoList = new ArrayList<>();
        for (SyncOrgInfoReq.PostInfo postInfo : syncOrgInfoDto.getPostInfoList()) {
            MbPostInfo mbPostInfo = new MbPostInfo();
            mbPostInfo.setOrgId(syncOrgInfoDto.getBasicInfo().getOrgId());
            mbPostInfo.setName(postInfo.getName());
            mbPostInfo.setIsDeleted(false);
            mbPostInfo.setDatachangeCreatetime(new Date());
            mbPostInfo.setDatachangeLasttime(new Date());
            mbPostInfoList.add(mbPostInfo);
        }
        return mbPostInfoList;
    }

    private List<MbExpressAddress> getDeliveryAddress(SyncOrgInfoReq.SyncOrganizationInfo syncOrgInfoDto) {
        List<MbExpressAddress> mbExpressAddressList = new ArrayList<>();
        for (SyncOrgInfoReq.DeliveryAddress deliveryAddress : syncOrgInfoDto.getDeliveryAddressList()) {
            MbExpressAddress temp = new MbExpressAddress();
            temp.setOrgId(syncOrgInfoDto.getBasicInfo().getOrgId());
            temp.setProvinceName(deliveryAddress.getProvinceName());
            temp.setCityName(deliveryAddress.getCityName());
            temp.setDistrictName(deliveryAddress.getDistrictName());
            temp.setAddress(deliveryAddress.getAddress());
            temp.setRecipientName(deliveryAddress.getRecipientName());
            temp.setCountryCode(deliveryAddress.getRecipientCountryCode());
            temp.setRecipientPhone(deliveryAddress.getRecipientPhone());
            temp.setPostCode(deliveryAddress.getPostCode());
            temp.setIsDefault(deliveryAddress.getIsDefault());
            temp.setIsCorporation(false);
            temp.setProvince(deliveryAddress.getProvince());
            temp.setCity(deliveryAddress.getCity());
            temp.setDistrict(deliveryAddress.getDistrict());
            mbExpressAddressList.add(temp);
        }
        return mbExpressAddressList;
    }

    private List<MbCommonInvoiceInfo> getInvoiceInfo(SyncOrgInfoReq.SyncOrganizationInfo syncOrgInfoDto) {
        List<MbCommonInvoiceInfo> mbCommonInvoiceInfoList = new ArrayList<>();
        for (SyncOrgInfoReq.InvoiceInfo invoiceInfo : syncOrgInfoDto.getInvoiceInfoList()) {
            MbCommonInvoiceInfo temp = new MbCommonInvoiceInfo();
            temp.setOrgId(syncOrgInfoDto.getBasicInfo().getOrgId());
            temp.setInvoiceTitle(invoiceInfo.getInvoiceTitle());
            temp.setTaxId(invoiceInfo.getTaxId());
            temp.setInvoiceType(1);
            temp.setCorporationAddress(invoiceInfo.getCorporationAddress());
            temp.setCorporationPhone(invoiceInfo.getCorporationPhone());
            temp.setAccountBank(invoiceInfo.getAccountBank());
            temp.setAccountCardNo(invoiceInfo.getAccountCardNo());
            temp.setDatachangeCreatetime(new Date());
            temp.setDatachangeLasttime(new Date());
            temp.setIsDeleted(false);
            mbCommonInvoiceInfoList.add(temp);
        }
        return mbCommonInvoiceInfoList;
    }

}
